package myJs.tool

import myJs.FileSaver
import myJs.myPkg.{FileInputOptions, LayerOptions}
import org.scalajs.dom.{BlobPropertyBag, Element, document, window}
import org.scalajs.dom.raw.Blob
import scalatags.Text.all._
import myJs.myPkg.jquery._
import myJs.Implicits._
import myJs.cps.Display

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import scala.scalajs.js.typedarray.Uint8Array
import scala.scalajs.js.JSConverters._

/**
 * Created by yz on 8/10/2021
 */
object Tool extends ProjectTool with TableFilterTool {

  val speciesMap = SeqMap("Macadamia integrifolia" -> "Macadamia integrifolia")
  val zhInfo = "Info"
  val layerOptions = LayerOptions(title = zhInfo, closeBtn = 0, skin = "layui-layer-molv", btn = List.empty[Int])
  val element = div()(
    span()("Running..."),
    " ",
    img(src := "/assets/images/running2.gif",
      width := 30,
      height := 20
    )()
  ).render
  val pattern = "yyyy-mm-dd"

  def revDict(dict: js.Dictionary[String]) = {
    dict.groupBy(_._2).mapValues(x => x.map(_._1))
  }

  def fillByNames(rs: js.Dictionary[String]) = {
    val names = $(".fillByName").mapElems { y =>
      $(y).attr("name").toString
    }.toArray
    names.foreach { name =>
      fillByName(rs, name)
    }
  }

  def fillByName(rs: js.Dictionary[String], name: String, parentId: String = "") = {
    val valOp = rs.get(name)
    valOp.foreach { value =>
      val parentElem = Tool.getParentElem(parentId)
      val jq = $(parentElem).findInputByName(name)
      jq.`val`(value)
      if (jq.hasClass("myMinicolors")) {
        jq.minicolors("value", js.Dictionary("color" -> s"${jq.myVal}"))
      }
    }
  }

  def fillByNameAndTriggers(rs: JDJAn, names: List[String]): Unit = {
    names.foreach { name =>
      fillByNameAndTrigger(rs, name)
    }
  }

  def fillByNameAndTrigger(rs: JDJAn, name: String, parentId: String = ""): JQuery = {
    val parentElem = Tool.getParentElem(parentId)
    val parentJq = $(parentElem)
    fillByNameAndTrigger(rs, name, parentJq)
  }

  def fillByNameAndTriggers(rs: JDJAn, parentId: String = ""): Unit = {
    val parentElem = Tool.getParentElem(parentId)
    val parentJq = $(s"${parentElem}")
    fillByNameAndTriggers(rs, parentJq)
  }

  def fillByNameAndTriggers(rs: JDJAn, parentJq: JQuery): Unit = {
    val names = parentJq.find(s".fillByNameAndTrigger").mapElems { y =>
      $(y).attr("name").toString
    }.toArray
    names.foreach { name =>
      fillByNameAndTrigger(rs, name, parentJq)
    }
  }

  def filterContentShow(y: Element, parentId: String) = {
    val parentJq = Tool.getParentJq(parentId)
    parentJq.find(s".filterContent").hide()
    val fieldName = Tool.getFilterDataFieldName(y)
    val idStr = s"${fieldName}Content".addQuotes
    val contentJq = parentJq.find(s"[id=${idStr}]")
    val yTop = $(y).offset().top + $(y).height() + 2
    val pageWidth = document.body.clientWidth
    val yTotalLeft = $(y).offset().left
    val leftWidth = $("#myLeft").width()
    val yLeft = yTotalLeft - leftWidth
    val width = 210
    val trueYLeft = if (yTotalLeft + width > pageWidth) pageWidth - leftWidth - 220 - 6 else yLeft
    contentJq.css("top", yTop.toInt).css("left", trueYLeft.toInt).width(width)
    contentJq.show()
    Tool.filterContentFillBeforeValue(contentJq)
  }

  def downloadPng(imageJq: JQuery, fileName: String) = {
    val src = imageJq.attr("src").get
    val base64 = src.replaceAll("^data:image/png;base64,", "")
    val byteArrays = base642binaryArray(base64)
    val blob = new Blob(byteArrays, BlobPropertyBag(`type` = "image/png"))
    FileSaver.saveAs(blob, fileName)
  }

  def base642binaryArray(content: String) = {
    val byteCharacters = window.atob(content)
    val sliceSize = 512
    val byteArrays = byteCharacters.grouped(sliceSize).map { slice =>
      val byteNumbers = slice.map(_.toShort).toJSArray
      new Uint8Array(byteNumbers)
    }
    byteArrays.toJSArray.map(_.asInstanceOf[js.Any])
  }

  def getParentJq(parentId: String) = {
    val y = getParentElem(parentId)
    $(y)
  }

  def getInputByName(name: String, parentId: String) = {
    val parentElem = Tool.getParentElem(parentId)
    $(s"${parentElem}").findInputByName(name)
  }

  def fillByNameAndTrigger(rs: JDJAn, name: String, parentJq: JQuery): JQuery = {
    val jq = parentJq.findInputByName(name)
    val value = rs(name)
    if (jq.hasClass("myToggle")) {
      if (value == null || value == "None" || value.toString == "false") {
        jq.bootstrapToggle("off")
      } else {
        jq.bootstrapToggle("on")
      }
    } else {
      jq.`val`(value.toString).trigger("change")
    }

  }

  def getParentElem(parentId: String) = {
    if (parentId.isEmpty) "body" else s"#${parentId}"
  }

  def downloadTxt(fileName: String, content: js.Any) = {
    val blob = new Blob(js.Array(content), BlobPropertyBag(`type` = "text/plain;charset=utf-8"))
    FileSaver.saveAs(blob, fileName)
  }

  def fileInput = {
    val options = FileInputOptions.showPreview(false).showUpload(false)
    $(".file").fileinput("destroy")
    $(".file").fileinput(options)
  }

  def getInputByName(name: String) = {
    $(s":input[name='${name}']")
  }

  def refreshCheckboxView(phenotypeNames: List[String], idStr: String) = {
    val html = phenotypeNames.map { x =>
      label(marginRight := 15,
        input(`type` := "checkbox", checked, value := x, onclick := s"Utils.setColumns('${x}')", x)
      )
    }.mkString
    $(s"#${idStr}").html(html)
  }

  def refreshCheckboxView(map: SeqMap[String, String], idStr: String) = {
    val html = map.map { case (v, showV) =>
      label(marginRight := 15,
        input(`type` := "checkbox", checked, value := v, onclick := s"Utils.setColumns(${v.addQuotes})", showV)
      )
    }.mkString
    $(s"#${idStr}").html(html)
  }

  def refreshCheckboxView(map: SeqMap[String, String], jq: JQuery, divId: String = "") = {
    val html = map.map { case (v, showV) =>
      label(marginRight := 15,
        input(`type` := "checkbox", checked, value := v, onclick := s"Utils.setColumns('${v}','${divId}')", showV)
      )
    }.mkString
    jq.html(html)
  }

  def b2Display(b: Boolean) = {
    if (b) Display.block else Display.none
  }

  def dbFmt(v: String) = {
    if (v.isDouble) {
      ujson.Num(v.toDouble)
    } else {
      ujson.Str(v)
    }
  }



}
